/*
 * rdp5.cpp
 *
 *  Created on: Oct 12, 2011
 *      Author: welcome
 */
#include <KD/kd.h>
#include <rdp5.h>
#include <string.h>
#include <rdp.h>
#include <orders.h>
#include <mppc.h>
#include <ui.h>

extern uint8 *g_next_packet;

extern RDPCOMP g_mppc_dict;

void rdp5_process(STREAM s) {
	printf("rdp5_process -> \n");

	uint16 length, count, x, y;
	uint8 type, ctype;
	uint8 *next;

	uint32 roff, rlen;
	struct stream *ns = &(g_mppc_dict.ns);
	struct stream *ts;
	ui_begin_update();
	while (s->p < s->end) {
		in_uint8(s, type);
		if (type & RDP5_COMPRESSED) {
			in_uint8(s, ctype);
			in_uint16_le(s, length);
			type ^= RDP5_COMPRESSED;
		} else {
			ctype = 0;
			in_uint16_le(s, length);
		}
		g_next_packet = next = s->p + length;

		if (ctype & RDP_MPPC_COMPRESSED) {
			if (mppc_expand(s->p, length, ctype, &roff, &rlen) == -1)
				error("error while decompressing packet\n");

			/* allocate memory and copy the uncompressed data into the temporary stream */
			ns->data = (uint8 *) kdRealloc(ns->data, rlen);

			memcpy((ns->data), (unsigned char *) (g_mppc_dict.hist + roff),
					rlen);

			ns->size = rlen;
			ns->end = (ns->data + ns->size);
			ns->p = ns->data;
			ns->rdp_hdr = ns->p;

			ts = ns;
		} else
			ts = s;

		switch (type) {
		case 0: /* update orders */
			printf("type == 0 \n");

			in_uint16_le(ts, count)
			;
			process_orders(ts, count);
			break;
		case 1: /* update bitmap */
			printf("type == 1 \n");
			in_uint8s(ts, 2)
			; /* part length */
			process_bitmap_updates(ts);
			break;
		case 2: /* update palette */
			printf("type == 2 \n");
			in_uint8s(ts, 2)
			; /* uint16 = 2 */
			process_palette(ts);
			break;
		case 3: /* update synchronize */
			printf("type == 3 \n");
			break;
		case 5: /* null pointer */
			printf("type == 5 \n");
			ui_set_null_cursor();
			break;
		case 6: /* default pointer */
			printf("type == 6 \n");
			break;
		case 8: /* pointer position */
			printf("type == 8 \n");
			in_uint16_le(ts, x)
			;
			in_uint16_le(ts, y)
			;
			if (s_check(ts))
				ui_move_pointer(x, y);
			break;
		case 9: /* color pointer */
			printf("type == 9 \n");
			process_colour_pointer_pdu(ts);
			break;
		case 10: /* cached pointer */
			printf("type == 10 \n");
			process_cached_pointer_pdu(ts);
			break;
		case 11:
			printf("type == 11 \n");
			process_new_pointer_pdu(ts);
			break;
		default:
			unimpl("RDP5 opcode %d\n", type);
		}

		s->p = next;
	}
	ui_end_update();
	printf("rdp5_process <- \n");
}
